package com.anhuanjia.tools.eao.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STUnderline;

import com.efastsoft.framework.utility.StringUtil;

/**
 * 通过word模板生成新的word工具类
 * 
 * @author
 * 
 */
public class XwpfTUtils {
	

	    /**
	     * 根据模板生成新word文档
	     * 判断表格是需要替换还是需要插入，判断逻辑有$为替换，表格无$为插入
	     * @param inputUrl 模板存放地址
	     * @param outPutUrl 新文档存放地址
	     * @param textMap 需要替换的信息集合
	     * @param tableList 需要插入的表格信息集合
	     * @return 成功返回true,失败返回false
	     */
	    public static boolean changWord(String inputUrl, String outputUrl,
	            Map<String, String> textMap, List<String[]> tableList) {

	        //模板转换默认成功
	        boolean changeFlag = true;
	        try {
	            //获取docx解析对象
	            XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
	            //解析替换文本段落对象
	            XwpfTUtils.changeText(document, textMap);
	            //解析替换表格对象
	           // XwpfTUtils.changeTable(document, textMap, tableList);

	            //生成新的word
	            File file = new File(outputUrl);
	            FileOutputStream stream = new FileOutputStream(file);
	            document.write(stream);
	            stream.close();

	        } catch (IOException e) {
	            e.printStackTrace();
	            changeFlag = false;
	        }

	        return changeFlag;

	    }

	    /**
	     * 替换段落文本
	     * @param document docx解析对象
	     * @param textMap 需要替换的信息集合
	     */
	    public static void changeText(XWPFDocument document, Map<String, String> textMap){
	        //获取段落集合
	        List<XWPFParagraph> paragraphs = document.getParagraphs();

	        for (XWPFParagraph paragraph : paragraphs) {
	            //判断此段落时候需要进行替换
	            String text = paragraph.getText();
	            if(checkText(text)){
	                List<XWPFRun> runs = paragraph.getRuns();
	                for (XWPFRun run : runs) {
	                    //替换模板原来位置
	                    run.setText(changeValue(run.toString(), textMap),0);
	                }
	            }else {
	            	System.out.println("未更改："+text);
	            }
	        }

	    }

	    /**
	     * 替换表格对象方法
	     * @param document docx解析对象
	     * @param textMap 需要替换的信息集合
	     * @param tableList 需要插入的表格信息集合
	     */
	    public static void changeTable(XWPFDocument document, Map<String, String> textMap,
	    		List<List<String[]>> tableLists){
	        //获取表格对象集合
	        List<XWPFTable> tables = document.getTables();
	        //遍历表格集合
	        for (int i = 0; i < tables.size(); i++) {
	            //只处理行数大于等于2的表格，且不循环表头
	            XWPFTable table = tables.get(i);
	           // if(table.getRows().size()>1){
	                //默认第一个表格为替换其他表格为插入
	                if(i<1){
	                    List<XWPFTableRow> rows = table.getRows();	 //获取表格行集合
	                    //遍历表格,并替换模板
	                    eachTable(rows, textMap);
	                    eachTable2(rows,textMap);
	                    eachTable3(rows,textMap);
	                }else{
	                	List<String[]> tableList = tableLists.get(i-1);
	                	insertTable(table, tableList);
	                }
	           //}
	        }
	    }
	    /**
	     * 替换表格对象方法不含插入
	     * @param document docx解析对象
	     * @param textMap 需要替换的信息集合
	     */
	    public static void changeTable3(XWPFDocument document, Map<String, String> textMap){
	    	//获取表格对象集合
	    	List<XWPFTable> tables = document.getTables();
	    	//遍历表格集合
	    	for (int i = 0; i < tables.size(); i++) {
	    		XWPFTable table = tables.get(i);
	    		List<XWPFTableRow> rows = table.getRows();	 //获取表格行集合
	    			//遍历表格,并替换模板
	    			eachTable(rows, textMap);
	    			eachTable2(rows,textMap);
	    			eachTable3(rows,textMap);
	    	}
	    }

	    /**
	     * 只插入表格对象方法
	     * @param document docx解析对象
	     * @param textMap 需要替换的信息集合
	     * @param tableList 需要插入的表格信息集合
	     */
	    public static void changeTable2(XWPFDocument document, Map<String, String> textMap,
	    		List<List<String[]>> tableLists){
	        //获取表格对象集合
	        List<XWPFTable> tables = document.getTables();
	        //遍历表格集合
	        for (int i = 0; i < tables.size(); i++) {
	            //只处理行数大于等于2的表格，且不循环表头
	            XWPFTable table = tables.get(i);
	           // if(table.getRows().size()>1){
	                List<String[]> tableList = tableLists.get(i);
	                insertTable(table, tableList);
	                
	           //}
	        }
	    }



	    /**
	     * 遍历表格
	     * @param rows 表格行对象
	     * @param textMap 需要替换的信息集合
	     */
	    public static void eachTable(List<XWPFTableRow> rows ,Map<String, String> textMap){
	        //遍历行集合获取单行集合
	    	for (XWPFTableRow row : rows) {			
	    		List<XWPFTableCell> cells = row.getTableCells();
	    		//遍历单行集合获取单元格集合	
	            for (XWPFTableCell cell : cells) {
	                //判断单元格是否需要替换
	                if(checkText(cell.getText())){
	                	//获取单元格中文本集合
	                	List<XWPFParagraph> paragraphs = cell.getParagraphs();
	                    //遍历文本集合获取文本段
	                	for (XWPFParagraph paragraph : paragraphs) {
	                        //获取文本段集合
	                		List<XWPFRun> runs = paragraph.getRuns();
	                        //遍历文本段并替换
	                		for (XWPFRun run : runs) {
	                            run.setText(changeValue(run.toString(), textMap),0);
	                        }
	                    }
	                }
	            }
	        }
	    }
	    /**
	     * 遍历表格替换为超链接
	     * @param rows 表格行对象
	     * @param textMap 需要替换的信息集合
	     */
	    public static void eachTable2(List<XWPFTableRow> rows ,Map<String, String> textMap){
	        //遍历行集合获取单行集合
	    	for (XWPFTableRow row : rows) {			
	    		List<XWPFTableCell> cells = row.getTableCells();
	    		//遍历单行集合获取单元格集合	
	            for (XWPFTableCell cell : cells) {
	                //判断单元格是否需要替换
	                if(checkText2(cell.getText())){
	                	//获取单元格中文本集合
	                	List<XWPFParagraph> paragraphs = cell.getParagraphs();
	                    //遍历文本集合获取文本段
	                	for (XWPFParagraph paragraph : paragraphs) {
	                        //获取文本段集合
	                		List<XWPFRun> runs = paragraph.getRuns();
	                        //遍历文本段并替换
	                		for (XWPFRun run : runs) {
	                			Set<Entry<String, String>> textSets = textMap.entrySet();
	                			String value =run.toString();
	                	        for (Entry<String, String> textSet : textSets) {
	                	            //匹配模板与替换值 格式^{key}
	                	        	String key = "^{"+textSet.getKey()+"}";
	                	           if(value!=null&&key!=null) {
	                	            if(value.indexOf(key)!= -1){
	                	            	value = textSet.getValue();
	                	            }
	                	            }
	                	        }
	                	        //模板未匹配到区域替换为空
	                	        if(checkText2(value)){
	                	            value = "";
	                	        }
	                			run.setText("",0);
	                			if(!StringUtil.isEmpty(value)) {
	                			appendExternalHyperlink(value,"点击查看", paragraph);
	                			}
	                		}
	                		
	                    }
	                }
	            }
	        }
	    }
	    /**
	     * 遍历表格替换图片
	     * @param rows 表格行对象
	     * @param textMap 需要替换的信息集合
	     */
	    public static void eachTable3(List<XWPFTableRow> rows ,Map<String, String> textMap){
	        //遍历行集合获取单行集合
	    	for (XWPFTableRow row : rows) {			
	    		List<XWPFTableCell> cells = row.getTableCells();
	    		//遍历单行集合获取单元格集合	
	            for (XWPFTableCell cell : cells) {
	                //判断单元格是否需要替换
	                if(checkText3(cell.getText())){
	                	//获取单元格中文本集合
	                	List<XWPFParagraph> paragraphs = cell.getParagraphs();
	                    //遍历文本集合获取文本段
	                	for (XWPFParagraph paragraph : paragraphs) {
	                        //获取文本段集合
	                		List<XWPFRun> runs = paragraph.getRuns();
	                        //遍历文本段并替换
	                		for (XWPFRun run : runs) {
	                			Set<Entry<String, String>> textSets = textMap.entrySet();
	                			String value =run.toString();
	                	        for (Entry<String, String> textSet : textSets) {
	                	            //匹配模板与替换值 格式^{key}
	                	        	String key = "#{"+textSet.getKey()+"}";
	                	           if(value!=null&&key!=null) {
	                	            if(value.indexOf(key)!= -1){
	                	            	value = textSet.getValue();
	                	            }
	                	            }
	                	        }
	                	        //模板未匹配到区域替换为空
	                	        if(checkText3(value)){
	                	            value = "";
	                	        }
	                			run.setText("",0);
	                			if(!StringUtil.isEmpty(value)) {
	                			appendImg(value,run);
	                			}
	                        }
	                    }
	                }
	            }
	        }
	    }
	    /**
	     * 为表格插入数据，行数不够添加新行
	     * @param table 需要插入数据的表格
	     * @param tableList 插入数据集合
	     */
	    public static void insertTable(XWPFTable table, List<String[]> tableList){
	
	        //创建行,根据需要插入的数据添加新行，不处理表头
	        for (int i = 0; i < tableList.size(); i++) {
	            XWPFTableRow row = table.createRow();
	        }
	        //遍历表格插入数据
	        List<XWPFTableRow> rows = table.getRows();
	        int length = table.getRows().size();
	        for (int i = 1; i < length - 1; i++) {
	            XWPFTableRow newRow = table.getRow(i);
	            List<XWPFTableCell> cells = newRow.getTableCells();
	            for (int j = 0; j < cells.size(); j++) {
	                XWPFTableCell cell = cells.get(j);
	                String s = tableList.get(i - 1)[j];
	                cell.setText(s);
	            }
	        }

	    }



	    /**
	     * 判断文本中时候包含$(文本)
	     * @param text 文本
	     * @return 包含返回true,不包含返回false
	     */
	    public static boolean checkText(String text){
	        boolean check  =  false;
	        if(text!=null) {
	        if(text.indexOf("$")!= -1){
	            check = true;
	        }
	        }
	        return check;

	    }
	    /**
	     * 判断文本中时候包含^(超链接)
	     * @param text 文本
	     * @return 包含返回true,不包含返回false
	     */
	    public static boolean checkText2(String text){
	        boolean check  =  false;
	        if(text!=null) {
	        if(text.indexOf("^")!= -1){
	            check = true;
	        }
	        }
	        return check;

	    }
	    /**
	     * 判断文本中时候包含#(图片)
	     * @param text 文本
	     * @return 包含返回true,不包含返回false
	     */
	    public static boolean checkText3(String text){
	        boolean check  =  false;
	        if(text!=null) {
	        if(text.indexOf("#")!= -1){
	            check = true;
	        }
	        }
	        return check;

	    }
	    /**
	     * 匹配传入信息集合与模板
	     * @param value 模板需要替换的区域
	     * @param textMap 传入信息集合
	     * @return 模板需要替换区域信息集合对应值
	     */
	    public static String changeValue(String value, Map<String, String> textMap){
	        Set<Entry<String, String>> textSets = textMap.entrySet();
	        for (Entry<String, String> textSet : textSets) {
	            //匹配模板与替换值 格式${key}
	            String key = "${"+textSet.getKey()+"}";
	           if(value!=null&&key!=null) {
	            if(value.indexOf(key)!= -1){
	                value = textSet.getValue();
	            }
	            }
	        }
	        //模板未匹配到区域替换为空
	        if(checkText2(value)){
	            value = "";
	        }
	        return value;
	    }
	    /**
	     * 匹配传入信息集合与模板
	     * @param value 模板需要替换的区域
	     * @param textMap 传入信息集合
	     * @return 模板需要替换区域信息集合对应值
	     */
	    public static String changeValue2(String value, Map<String, String> textMap){
	        Set<Entry<String, String>> textSets = textMap.entrySet();
	        for (Entry<String, String> textSet : textSets) {
	            //匹配模板与替换值 格式^{key}
	            String key = "^{"+textSet.getKey()+"}";
	           if(value!=null&&key!=null) {
	            if(value.indexOf(key)!= -1){
	                value = textSet.getValue();
	            }
	            }
	        }
	        //模板未匹配到区域替换为空
	        if(checkText(value)){
	            value = "";
	        }
	        return value;
	    }
	    
	    /**
		 * Appends an external hyperlink to the paragraph. 追加超链接
		 *@see  详细代码见http://stackoverflow.com/questions/7007810/how-to-create-a-email-link-in-poi-word-format            
		 */
		public static void appendExternalHyperlink(String url, String text,
				XWPFParagraph paragraph) {
			// Add the link as External relationship
			String id = paragraph
					.getDocument()
					.getPackagePart()
					.addExternalRelationship(url,
							XWPFRelation.HYPERLINK.getRelation()).getId();
			// Append the link and bind it to the relationship
			CTHyperlink cLink = paragraph.getCTP().addNewHyperlink();
			cLink.setId(id);
			
			// Create the linked text
			CTText ctText = CTText.Factory.newInstance();
			ctText.setStringValue(text);
			CTR ctr = CTR.Factory.newInstance();
			CTRPr rpr = ctr.addNewRPr();
			
			//设置超链接样式
			CTColor color = CTColor.Factory.newInstance();
			color.setVal("0000FF");
			rpr.setColor(color);
			rpr.addNewU().setVal(STUnderline.SINGLE);
			
			//设置字体
			CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr.addNewRFonts();
			fonts.setAscii("微软雅黑");
			fonts.setEastAsia("微软雅黑");
			fonts.setHAnsi("微软雅黑");

			//设置字体大小
			CTHpsMeasure sz = rpr.isSetSz() ? rpr.getSz() : rpr.addNewSz();
			sz.setVal(new BigInteger("24"));

			ctr.setTArray(new CTText[] { ctText });
			// Insert the linked text into the link
			cLink.setRArray(new CTR[] { ctr });
			
			//设置段落居中
			//paragraph.setAlignment(ParagraphAlignment.CENTER);
			//paragraph.setVerticalAlignment(TextAlignment.CENTER);
		}
			/**
			 * 	追加超链接	
			 * @param url 
			 * @param text
			 * @param cell
			 */
		public void appendExternalHyperlink(String url, String text,XWPFTableCell cell) {
	        XWPFParagraph p=getCellFirstParagraph(cell);
	        String id = p.getDocument().getPackagePart().addExternalRelationship(url,XWPFRelation.HYPERLINK.getRelation()).getId();
	        CTHyperlink link = p.getCTP().addNewHyperlink();
	        link.setId(id);

	        CTText ctText = CTText.Factory.newInstance();
	        ctText.setStringValue(text);
	        CTR ctr = CTR.Factory.newInstance();
	        CTRPr rpr = ctr.addNewRPr();

	        //设置超链接样式
	        CTColor color = CTColor.Factory.newInstance();
	        color.setVal("0000FF");
	        rpr.setColor(color);
	        rpr.addNewU().setVal(STUnderline.SINGLE);

	        ctr.setTArray(new CTText[]{ctText});
	        link.setRArray(new CTR[]{ctr});

	        //垂直居中
	        cell.setVerticalAlignment(XWPFVertAlign.CENTER);
	        //水平居中
	        p.setAlignment(ParagraphAlignment.CENTER);

		}

	  /*  public static void main(String[] args) {
	        //模板文件地址
	        String inputUrl = "C:\\Users\\Administrator.PC-201807211757\\git\\data\\src\\001.docx";
	        //新生产的模板文件
	        String outputUrl = "C:\\Users\\Administrator.PC-201807211757\\git\\data\\test1.docx";

	        Map<String, String> testMap = new HashMap<String, String>();
	        testMap.put("name", "小明");
	        testMap.put("sex", "男");
	        testMap.put("address", "软件园");
	        testMap.put("phone", "88888888");

	        List<String[]> testList = new ArrayList<String[]>();
	        testList.add(new String[]{"1","1AA","1BB","1CC"});
	        testList.add(new String[]{"2","2AA","2BB","2CC"});
	        testList.add(new String[]{"3","3AA","3BB","3CC"});
	        testList.add(new String[]{"4","4AA","4BB","4CC"});

	        XwpfTUtils.changWord(inputUrl, outputUrl, testMap, testList);
	    }*/
		/** 
	     * @Description: 得到单元格第一个Paragraph 
	     */  
	    public XWPFParagraph getCellFirstParagraph(XWPFTableCell cell) {  
	        XWPFParagraph p;  
	        if (cell.getParagraphs() != null && cell.getParagraphs().size() > 0) {  
	            p = cell.getParagraphs().get(0);  
	        } else {  
	            p = cell.addParagraph();  
	        }  
	        return p;  
	    }  
	   
	    
	    /**
	     * 设置图片
	     * @param imgFile 可运行图片
	     * @param r	文本
	     * @return
	     */
	    
	    public static String appendImg(String imgFile,XWPFRun r) {
			int format = 0 ;

	        if(imgFile.endsWith(".emf")) format = XWPFDocument.PICTURE_TYPE_EMF;
	        else if(imgFile.endsWith(".wmf")) format = XWPFDocument.PICTURE_TYPE_WMF;
	        else if(imgFile.endsWith(".pict")) format = XWPFDocument.PICTURE_TYPE_PICT;
	        else if(imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) format = XWPFDocument.PICTURE_TYPE_JPEG;
	        else if(imgFile.endsWith(".png")) format = XWPFDocument.PICTURE_TYPE_PNG;
	        else if(imgFile.endsWith(".dib")) format = XWPFDocument.PICTURE_TYPE_DIB;
	        else if(imgFile.endsWith(".gif")) format = XWPFDocument.PICTURE_TYPE_GIF;
	        else if(imgFile.endsWith(".tiff")) format = XWPFDocument.PICTURE_TYPE_TIFF;
	        else if(imgFile.endsWith(".eps")) format = XWPFDocument.PICTURE_TYPE_EPS;
	        else if(imgFile.endsWith(".bmp")) format = XWPFDocument.PICTURE_TYPE_BMP;
	        else if(imgFile.endsWith(".wpg")) format = XWPFDocument.PICTURE_TYPE_WPG;
	        else {
	            System.err.println("Unsupported picture: " + imgFile +
	                    ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
	            
	            return "文件不支持";
	        }
	      //  r.setText(imgFile);
	        r.addBreak();
	        try {
				r.addPicture(new FileInputStream(imgFile), format, imgFile, Units.toEMU(100), Units.toEMU(100));
			} catch (InvalidFormatException | IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} // 200x200 pixels
	        r.addBreak(BreakType.PAGE);
			return "已设置";
	        
	        
		}
	    
	}


